#include "teachmode.h"
#include "ui_teachmode.h"
#include <QInputDialog>

TeachMode::TeachMode(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TeachMode)
{
    ui->setupUi(this);

    ui->widget->setAutoFillBackground(true);
    QPalette palette = ui->widget->palette();
    palette.setColor(QPalette::Background, Qt::white);
    ui->widget->setPalette(palette);

    QString str = "自动运行 / 第1页";
    ui->label_pagedisplay->setText(str);

    ui->stackedWidget->setCurrentIndex(0);
    QWidget* pages1[] = { ui->page, ui->page_2, ui->page_3 };
    QWidget* pages2[] = { ui->page_4 };
    QWidget* pages3[] = { ui->page_5, ui->page_6, ui->page_7 };
    QWidget* pages4[] = { ui->page_8, ui->page_9, ui->page_10 };
    ProgramCategoryChosen = new int(0);
    pageCount = new int[4];
    pageCount[0] = sizeof(pages1) / sizeof(pages1[0]); // 3
    pageCount[1] = sizeof(pages2) / sizeof(pages2[0]) + pageCount[0]; // 4
    pageCount[2] = sizeof(pages3) / sizeof(pages3[0]) + pageCount[1]; // 7
    pageCount[3] = sizeof(pages4) / sizeof(pages4[0]) + pageCount[2]; // 10

    connectButtonsAndSignals();

    softKeyboard = new SoftKeyboard();
    ui->frame->hide();

    loadSavedButtons();
}


void TeachMode::connectButtonsAndSignals() {
    connect(ui->pushButton_7, &QPushButton::clicked, this, [&]() {
        handlePageSwitch(0, pageCount, ProgramCategoryChosen);
        changeLabelPageDisplay();
    });
    connect(ui->pushButton_8, &QPushButton::clicked, this, [&]() {
        handlePageSwitch(1, pageCount, ProgramCategoryChosen);
        changeLabelPageDisplay();
    });

    connect(ui->pushButton, &QPushButton::clicked, this, [&]() {
        if(*ProgramCategoryChosen != 0)
        {
            ui->stackedWidget->setCurrentIndex(0);
            *ProgramCategoryChosen = 0;
            changeLabelPageDisplay();
        }
    });
    connect(ui->pushButton_2, &QPushButton::clicked, this, [&]() {
        if(*ProgramCategoryChosen != 1)
        {
            ui->stackedWidget->setCurrentIndex(pageCount[0]);
            *ProgramCategoryChosen = 1;
            changeLabelPageDisplay();
        }
    });
    connect(ui->pushButton_3, &QPushButton::clicked, this, [&]() {
        if(*ProgramCategoryChosen != 2)
        {
            ui->stackedWidget->setCurrentIndex(pageCount[1]);
            *ProgramCategoryChosen = 2;
            changeLabelPageDisplay();
        }
    });
    connect(ui->pushButton_4, &QPushButton::clicked, this, [&]() {
        if(*ProgramCategoryChosen != 3)
        {
            ui->stackedWidget->setCurrentIndex(pageCount[2]);
            *ProgramCategoryChosen = 3;
            changeLabelPageDisplay();
        }
    });

    connect(ui->returnMenu, &QPushButton::clicked, this, &TeachMode::pushReturnMenu);
    connect(ui->pushButton_5, &QPushButton::clicked, this, &TeachMode::addNewProgram);
    connect(ui->pushButton_6, &QPushButton::clicked, this, &TeachMode::deleteNewProgram);
    connect(ui->pushButton_9, &QPushButton::clicked, this, &TeachMode::setButton);
    connect(ui->pushButton_10, &QPushButton::clicked, this, &TeachMode::disableButton);
}

//************  save funcs ************//
void TeachMode::loadSavedButtons() {
    tinyxml2::XMLDocument doc;
    if (doc.LoadFile(docPath) != tinyxml2::XML_SUCCESS) {
        qDebug() << "Error loading XML file when loading programfile";
        return;
    }
    tinyxml2::XMLElement* root = doc.RootElement();
    if (!root) {
        qDebug() << "No root element found in XML file Flexible2ControllerData.xml.";
        return;
    }

    tinyxml2::XMLElement* programElement = root->FirstChildElement("ProgramElement");
    if (!programElement) {
        qDebug() << "No ProgramElement element found in XML file Flexible2ControllerData.xml.";
        return;
    }
    for (tinyxml2::XMLElement* programNameElement = programElement->FirstChildElement("ProgramName");
            programNameElement;
            programNameElement = programNameElement->NextSiblingElement("ProgramName"))
    {
        QString buttonName = programNameElement->Attribute("ProgramName");
        int currentPage = programNameElement->IntAttribute("Page", 0);
        int x = programNameElement->IntAttribute("X", 0);
        int y = programNameElement->IntAttribute("Y", 0);
        if(buttonName!="自动运转程序") {
            QPushButton* newButton = createNewButton(buttonName, currentPage);
            connectNewButton(newButton);
            setButtonGeometry(newButton, x, y);
            pageProgram[calculateInWhichPage(currentPage)]++;
        }
    }
}

void TeachMode::saveButtonInfo(const QString& buttonName, int currentPage, int x, int y) {
    tinyxml2::XMLDocument doc;

    if (doc.LoadFile(docPath) != tinyxml2::XML_SUCCESS) {
        qDebug() << "Error loading XML file when saving programfile";
        return;
    }
    tinyxml2::XMLElement* root = doc.RootElement();
    if (!root) {
        root = doc.NewElement("ProgramElement");
        doc.InsertEndChild(root);
    }

    tinyxml2::XMLElement* programElement = root->FirstChildElement("ProgramElement");
    if (!programElement) {
        programElement = doc.NewElement("ProgramElement");
        root->InsertEndChild(programElement);
    }

    tinyxml2::XMLElement* existingElement = programElement->FirstChildElement(
                    "ProgramName");
    while (existingElement) {
        const char* existingName = existingElement->Attribute("ProgramName");
        if (existingName && QString(existingName) == buttonName) {
            existingElement->SetAttribute("Page", currentPage);
            existingElement->SetAttribute("X", x);
            existingElement->SetAttribute("Y", y);
            doc.SaveFile(docPath);
            return;
        }
        existingElement = existingElement->NextSiblingElement("ProgramName");
    }

    tinyxml2::XMLElement* ProgramName = doc.NewElement("ProgramName");
    ProgramName->SetAttribute("ProgramName", buttonName.toStdString().c_str());
    ProgramName->SetAttribute("Page", currentPage);
    ProgramName->SetAttribute("X", x);
    ProgramName->SetAttribute("Y", y);

    programElement->InsertEndChild(ProgramName);
    doc.SaveFile(docPath);
}

void TeachMode::handleButtonDeletion(QPushButton* buttonToDelete, int currentPageIndex) {
    deletedButtonsPositions.append(buttonToDelete->pos());
    buttonToDelete->hide();
    buttonToDelete->deleteLater();
    pageButton[currentPageIndex]--;

    QString buttonName = buttonToDelete->text();
    createdButtons.removeAll(buttonToDelete);

    tinyxml2::XMLDocument doc;
    if (doc.LoadFile(docPath) != tinyxml2::XML_SUCCESS) {
        qDebug() << "Error loading XML file when deleting programfile";
        return;
    }
    tinyxml2::XMLElement* root = doc.RootElement();
    tinyxml2::XMLElement* programElement = root->FirstChildElement("ProgramElement");
    if (!programElement) {
        qDebug() << "No ProgramElement element found in XML file Flexible2ControllerData.xml.";
        return;
    }

    for (tinyxml2::XMLElement* ProgramName = programElement->FirstChildElement("ProgramName");
            ProgramName; ProgramName = ProgramName->NextSiblingElement("ProgramName")) {
        if (ProgramName->Attribute("ProgramName") == buttonName.toStdString()) {
            ProgramName->DeleteChild(ProgramName);
            break;
        }
    }

    doc.SaveFile(docPath);
}

//************  slots funcs ************//
void TeachMode::addNewProgram()
{
    ui->frame->show();
    ui->lineEdit->setFocus();
    ui->lineEdit->installEventFilter(this);
}

void TeachMode::deleteNewProgram() {
    int currentPageIndex = ui->stackedWidget->currentIndex();
    QWidget* currentPage = ui->stackedWidget->widget(currentPageIndex);
    QList<QPushButton*> buttonsOnCurrentPage = currentPage->findChildren<QPushButton*>();

    if (buttonsOnCurrentPage.isEmpty()) {
        return;
    }

    QStringList buttonTexts;
    for (auto button : buttonsOnCurrentPage) {
        if (isButtonCreated(button)) {
            buttonTexts.append(button->text());
        }
    }

    bool ok;
    QString itemText = QInputDialog::getItem(this, "选择按钮",
                                                "选择要删除的按钮:", buttonTexts, 0, false, &ok);
    if (ok) {
        int index = buttonTexts.indexOf(itemText);

        if (isValidButtonIndex(index, buttonsOnCurrentPage.size())) {
            QPushButton *buttonToDelete = buttonsOnCurrentPage.at(index);
            handleButtonDeletion(buttonToDelete, currentPageIndex);
        }
    }
}

void TeachMode::setButton() {
    int currentPage = ui->stackedWidget->currentIndex();
    QString buttonName = ui->lineEdit->text();
    ui->frame->hide();
    ui->lineEdit->setText("");
    if (isButtonNameUnique(buttonName)) {
        int x, y;
        if(!isReachCapacityLimit())
        {
            calculateButtonPosition(currentPage, x, y);
            if (pageButton[currentPage] <= 22) {
                QPushButton* newButton = createNewButton(buttonName, currentPage);
                newButton->setFixedSize(180, 30);
                if (newButton) {
                    connectNewButton(newButton);
                    setButtonGeometry(newButton, x, y);
                    saveButtonInfo(buttonName, currentPage, x, y);
                }
            }
        }
    }
}

void TeachMode::disableButton()
{
    ui->frame->hide();
    ui->lineEdit->setText("");
}

//************  auxiliary  funcs ************//
void TeachMode::changeProgramEditAuthority() {
    if(pendantInterfaceData.actionMode == "手动操作")
    {
        ui->pushButton_5->show();
        ui->pushButton_6->show();
    }
    else
    {
        ui->pushButton_5->hide();
        ui->pushButton_6->hide();
    }
}

void TeachMode::changeLabelPageDisplay() {
    int currentPageIndex = ui->stackedWidget->currentIndex();
    int displayedPageIndex = 0;
    calculateInWhichPage(currentPageIndex);
    QString str1;
    switch (*ProgramCategoryChosen) {
        case 0: str1 = "自动运行"; displayedPageIndex = currentPageIndex + 1; break;
        case 1: str1 = "原点复归"; displayedPageIndex= currentPageIndex - pageCount[0] + 1; break;
        case 2: str1 = "手动操作"; displayedPageIndex= currentPageIndex - pageCount[1] + 1; break;
        case 3: str1 = "系统程序"; displayedPageIndex= currentPageIndex - pageCount[2] + 1; break;
        default: break;
    }
    QString str2 = " / ";
    QString str3 = "第";
    QString str4 =  QString::number(displayedPageIndex);
    QString str5 = "页";
    QString result = str1 + str2 + str3 + str4 + str5;
    ui->label_pagedisplay->setText(result);
}

bool TeachMode::isReachCapacityLimit() {
    switch(*ProgramCategoryChosen)
    {
        case 0: if(pageProgram[0] >= pageProgramCapacity[0]){return true;} break;
        case 1: if(pageProgram[1] >= pageProgramCapacity[1]){return true;} break;
        case 2: if(pageProgram[2] >= pageProgramCapacity[2]){return true;} break;
        case 3: if(pageProgram[3] >= pageProgramCapacity[3]){return true;} break;
        default: return false; break;
    }
    return false;
}

bool TeachMode::isButtonPositionUnique(int x, int y) {
    int currentPage = ui->stackedWidget->currentIndex();

    for (QPushButton* existingButton : createdButtons) {
        int existingX = existingButton->x();
        int existingY = existingButton->y();
        int existingPage = existingButton->property("Page").toInt();

        if (x >= existingX && x <= (existingX + 181) &&
            y >= existingY && y <= (existingY + 31) &&
            existingPage == currentPage) {
                return false;
        }
    }
    return true;
}


bool TeachMode::isButtonNameUnique(const QString& buttonName) {
    for (QPushButton* existingButton : createdButtons) {
        if (existingButton->text() == buttonName) {
            return false;
        }
    }
    return true;
}

QPushButton* TeachMode::createNewButton(const QString& buttonName, int currentPage) {
    QWidget* currentPageWidget = ui->stackedWidget->widget(currentPage);

    QPushButton* newButton = new QPushButton(buttonName, currentPageWidget);
    newButton->setObjectName(buttonName);
    newButton->setProperty("Page", currentPage);
    newButton->show();
    createdButtons.append(newButton);
    return newButton;
}

void TeachMode::connectNewButton(QPushButton* newButton) {
    connect(newButton, &QPushButton::clicked, this, [=]() {
        emit go2ProgramEditor_(newButton->text());
    });
}

void TeachMode::calculateButtonPosition(int& currentPage, int& x, int& y) {
    if (!deletedButtonsPositions.isEmpty()) {
        QPoint position = deletedButtonsPositions.takeFirst();
        x = position.x();
        y = position.y();
        pageButton[currentPage]++;
    } else {
        const int xOffset = 25;
        const int yOffset = 10;
        do {
            x = ((pageButton[currentPage] - 1) % 3) * 180 + (((pageButton[currentPage] - 1) % 3) + 1) * xOffset;
            y = ((pageButton[currentPage] - 1) / 3) * 30 + (((pageButton[currentPage] - 1) / 3) + 1) * yOffset;
            if (pageButton[currentPage] < 22) {
                pageButton[currentPage]++;
            } else {
                currentPage++;
                ui->stackedWidget->setCurrentIndex(currentPage);
                changeLabelPageDisplay();
                calculateButtonPosition(currentPage, x, y);
            }
        } while (!isButtonPositionUnique(x, y));
    }
    pageProgram[calculateInWhichPage(currentPage)]++;
}

int TeachMode::calculateInWhichPage(int& currentPage) {
    if(currentPage <= pageCount[0]-1)
    {
        return 0;
    }
    if(currentPage > pageCount[0]-1 && currentPage <= pageCount[1]-1)
    {
        return 1;
    }
    if(currentPage > pageCount[1]-1 && currentPage <= pageCount[2]-1)
    {
        return 2;
    }
    if(currentPage > pageCount[2]-1 && currentPage <= pageCount[3]-1)
    {
        return 3;
    }
    return 0;
}

void TeachMode::setButtonGeometry(QPushButton* newButton, int x, int y) {
    const int buttonWidth = 181;
    const int buttonHeight = 31;
    newButton->setGeometry(x, y, buttonWidth, buttonHeight);
}


bool TeachMode::isButtonCreated(QPushButton* button) {
    return createdButtons.contains(button);
}

bool TeachMode::isValidButtonIndex(int index, int buttonCount) {
    return (index >= 0 && index < buttonCount);
}


TeachMode::~TeachMode()
{
    delete ui;
    delete softKeyboard;
}

void TeachMode::handlePageSwitch(int buttonIndex, int* pageCount,int* pagechose) {
    int currentIndex = ui->stackedWidget->currentIndex();
    if (buttonIndex == 0 && currentIndex > pageCount[*pagechose - 1]) {
        ui->stackedWidget->setCurrentIndex(currentIndex - 1);
    } else if (buttonIndex == 1 && currentIndex < pageCount[*pagechose] - 1) {
        ui->stackedWidget->setCurrentIndex(currentIndex + 1);
    }
}

void TeachMode::pushReturnMenu()
{
    emit returnMenu();
}

bool TeachMode::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type()==QEvent::MouseButtonRelease)
    {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        if(mouseEvent->button() == Qt::LeftButton)
        {
            QPoint point = this->pos();
            if(watched == ui->lineEdit)
            {
                softKeyboard->hideInputBufferArea(ui->lineEdit);
                softKeyboard->resize(100,120);
                softKeyboard->move(point+ui->lineEdit->pos());
                softKeyboard->show();
            }
        }
    }
    return QWidget::eventFilter(watched,event);
}
